home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Speccy ClassiX 1998
/
Speccy ClassiX 98.iso
/
amiga_system
/
the_aminet
/
dev
/
gcc
/
ixemulsrc.lha
/
ixemul-41.4
/
library
/
socket.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-09-27
|
29KB
|
1,301 lines
/*
* This file is part of ixemul.library for the Amiga.
* Copyright (C) 1991, 1992 Markus M. Wild
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
* socket.c,v 1.1.1.1 1994/04/04 04:29:41 amiga Exp
*
* socket.c,v
* Revision 1.1.1.1 1994/04/04 04:29:41 amiga
* Initial CVS check in.
*
* Revision 1.2 1993/11/05 22:02:33 mwild
* inet.library code, plus NOT YET WORKING code for "own" sockets
*
*/
#define KERNEL
#include "ixemul.h"
#include "kprintf.h"
#include <sys/socket.h>
#include <sys/socketvar.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <net/route.h>
#include <netinet/in.h>
#include "select.h"
#include <machine/param.h>
static struct file *getsock (int fdes);
static int soo_read (struct file *fp, char *buf, int len);
static int soo_write (struct file *fp, char *buf, int len);
static int soo_ioctl (struct file *fp, int cmd, int inout, int arglen, caddr_t data);
static int soo_select(struct file *fp, int select_cmd, int io_mode);
static int soo_close (struct file *fp);
/* inet.library is just as weird as ixemul.library... it takes all parameters
in parameter structures, addressed by d1 (a datareg taking an address..). */
#include "inet.h"
int
socket (int domain, int type, int protocol)
{
struct a {
short domain;
short type;
short protocol;
char sigurg;
char sigio;
short err;
struct socket *so;
} uap;
struct socket *so;
struct file *fp;
struct user *p = &u;
int fd, err, ostat, omask;
if (domain == AF_INET && ! p->u_InetBase)
{
errno = ENOSYS;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return -1;
}
ostat = p->p_stat;
p->p_stat = SWAIT;
omask = syscall (SYS_sigsetmask, ~0);
do
{
if (err = falloc (&fp, &fd))
break;
#if defined (U_SOCKETS)
if (domain == AF_INET)
{
#endif
uap.domain = domain;
uap.type = type;
uap.protocol = protocol;
uap.sigurg = u.u_sigurg;
uap.sigio = u.u_sigio;
uap.err = 0;
IN_socket(p->u_InetBase, &uap);
fp->f_so = uap.so;
err = uap.err;
#if defined (U_SOCKETS)
}
else
{
err = socreate (domain, &so, type, protocol);
}
#endif
if (err)
{
/* free the allocated fd */
p->u_ofile[fd] = 0;
fp->f_count = 0;
break;
}
fp->f_stb.st_mode = 0666 | S_IFSOCK; /* not always, but.. */
fp->f_stb.st_size = 128; /* sizeof mbuf. */
fp->f_stb.st_blksize = 128;
fp->f_flags = FREAD|FWRITE;
fp->f_type = domain == AF_INET ? DTYPE_SOCKET : DTYPE_USOCKET;
fp->f_read = soo_read;
fp->f_write = soo_write;
fp->f_ioctl = soo_ioctl;
fp->f_close = soo_close;
fp->f_select = soo_select;
}
while (0);
syscall (SYS_sigsetmask, omask);
if (CURSIG (p))
SetSignal (0, SIGBREAKF_CTRL_C);
p->p_stat = ostat;
if (err == EINTR)
setrun (FindTask (0));
errno = err;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return err ? -1 : fd;
}
int
bind (int s, caddr_t name, int namelen)
{
struct a {
struct socket *so;
caddr_t name;
short namelen;
short err;
} uap;
register struct file *fp = getsock (s);
struct user *p = &u;
int ostat, error;
if (! fp)
return -1;
ostat = p->p_stat;
p->p_stat = SWAIT;
#if defined (U_SOCKETS)
if (fp->f_type == DTYPE_SOCKET)
{
#endif
uap.so = fp->f_so;
uap.name = name;
uap.namelen = namelen;
uap.err = 0;
IN_bind(p->u_InetBase, &uap);
error = uap.err;
#if defined (U_SOCKETS)
}
else
{
struct mbuf *nam;
error = sockargs (&nam, name, namelen, MT_SONAME);
if (! error)
{
error = sobind (fp->f_so, nam);
m_freem (nam);
}
}
#endif
if (CURSIG (p))
SetSignal (0, SIGBREAKF_CTRL_C);
p->p_stat = ostat;
if (error == EINTR)
setrun (FindTask (0));
errno = error;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return error ? -1 : 0;
}
int
listen (int s, int backlog)
{
struct a {
struct socket *so;
short backlog;
short err;
} uap;
register struct file *fp = getsock (s);
struct user *p = &u;
int ostat, error;
if (! fp)
return -1;
ostat = p->p_stat;
p->p_stat = SWAIT;
#if defined (U_SOCKETS)
if (fp->f_type == DTYPE_SOCKET)
{
#endif
uap.so = fp->f_so;
uap.backlog = backlog;
uap.err = 0;
IN_listen(p->u_InetBase, &uap);
error = uap.err;
#if defined (U_SOCKETS)
}
else
{
error = solisten (fp->f_so, backlog);
}
#endif
if (CURSIG (p))
SetSignal (0, SIGBREAKF_CTRL_C);
p->p_stat = ostat;
if (error == EINTR)
setrun (FindTask (0));
errno = error;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return error ? -1 : 0;
}
int
accept (int s, caddr_t name, int *namelen)
{
struct a {
struct socket *so;
caddr_t name;
short namelen;
short err;
struct socket *so2;
} uap;
struct file *fp = getsock (s), *fp2;
struct user *p = &u;
int err, fd2, ostat;
if (! fp)
return -1;
ostat = p->p_stat;
p->p_stat = SWAIT;
do
{
/* first try to get a new descriptor. If that fails, don't even
bother to call the library */
if (err = falloc (&fp2, &fd2))
break;
#if defined (U_SOCKETS)
if (fp->f_type == DTYPE_SOCKET)
{
#endif
uap.so = fp->f_so;
uap.name = name;
uap.namelen = namelen ? *namelen : 0;
uap.so2 = 0;
uap.err = 0;
IN_accept(p->u_InetBase, &uap);
if (! uap.so2 && !uap.err)
uap.err = EINTR; /* XXX */
err = uap.err;
if (namelen)
*namelen = uap.namelen;
fp2->f_so = uap.so2;
#if defined (U_SOCKETS)
}
else
{
struct socket *so = fp->f_so;
if ((so->so_options & SO_ACCEPTCONN) == 0)
err = EINVAL;
else if ((so->so_state & SS_NBIO) && so->so_qlen == 0)
err = EWOULDBLOCK;
else
{
while (so->so_qlen == 0 && so->so_error == 0)
{
if (so->so_state & SS_CANTRCVMORE)
{
so->so_error = ECONNABORTED;
break;
}
if (err = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
netcon, 0))
{
so->so_error = err;
break;
}
}
if (so->so_error)
{
err = so->so_error;
so->so_error = 0;
}
else
{
struct socket *aso = so->so_q;
struct mbuf *nam;
if (soqremque (aso, 1) == 0)
panic ("accept");
fp2->f_so = aso;
nam = m_get (M_WAIT, MT_SONAME);
(void) soaccept (aso, nam);
if (name && namelen)
{
if (*namelen > nam->m_len)
*namelen = nam->m_len;
bcopy (mtod (nam, caddr_t), name, *namelen);
}
m_freem (nam);
}
}
}
#endif
if (err)
{
/* free the second file */
u.u_ofile[fd2] = 0;
fp2->f_count = 0;
break;
}
fp2->f_stb.st_mode = 0666 | S_IFSOCK; /* not always, but.. */
fp2->f_stb.st_size = 128; /* sizeof mbuf.. */
fp2->f_stb.st_blksize = 128;
fp2->f_flags = FREAD|FWRITE;
fp2->f_type = DTYPE_SOCKET;
fp2->f_read = soo_read;
fp2->f_write = soo_write;
fp2->f_ioctl = soo_ioctl;
fp2->f_close = soo_close;
fp2->f_select = soo_select;
}
while (0);
if (CURSIG (p))
SetSignal (0, SIGBREAKF_CTRL_C);
p->p_stat = ostat;
if (err == EINTR)
setrun (FindTask (0));
errno = err;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return err ? -1 : fd2;
}
int
connect (int s, caddr_t name, int namelen)
{
struct a {
struct socket *so;
caddr_t name;
short namelen;
short err;
} uap;
register struct file *fp = getsock (s);
struct user *p = &u;
int ostat, error;
if (! fp)
return -1;
ostat = p->p_stat;
p->p_stat = SWAIT;
#if defined (U_SOCKETS)
if (fp->f_type == DTYPE_SOCKET)
{
#endif
uap.so = fp->f_so;
uap.name = name;
uap.namelen = namelen;
uap.err = 0;
IN_connect(p->u_InetBase, &uap);
error = uap.err;
#if defined (U_SOCKETS)
}
else
{
struct socket *so = fp->f_so;
struct mbuf *nam;
if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))
{
error = EALREADY;
break;
}
if (error = sockargs(&nam, name, namelen, MT_SONAME))
break;
error = soconnect(so, nam);
if (error)
goto bad;
if ((so->so_state & SS_NBIO) && (so->so_state & SS_ISCONNECTING))
{
m_freem(nam);
error = EINPROGRESS;
}
Forbid ();
while ((so->so_state & SS_ISCONNECTING) && so->so_error == 0)
if (error = tsleep((caddr_t)&so->so_timeo, PSOCK | PCATCH,
netcon, 0))
break;
if (error == 0)
{
error = so->so_error;
so->so_error = 0;
}
Permit ();
bad:
so->so_state &= ~SS_ISCONNECTING;
m_freem(nam);
if (error == ERESTART)
error = EINTR;
}
#endif
if (CURSIG (p))
SetSignal (0, SIGBREAKF_CTRL_C);
p->p_stat = ostat;
if (error == EINTR)
setrun (FindTask (0));
errno = error;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return error ? -1 : 0;
}
#if 0
/* This function is not available with Commodore sockets. */
int
socketpair (int domain, int type, int protocol, int sv[2])
{
register struct file *fp1, *fp2;
struct socket *so1, *so2;
struct user *p = &u;
int ostat, error;
/* minimal test.. */
if (!sv[0] || !sv[1])
{
errno = EFAULT;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return -1;
}
/* no go with Commo-sockets */
if (domain == AF_INET)
{
errno = EPFNOSUPPORT;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return -1;
}
ostat = p->p_stat;
p->p_stat = SWAIT;
do
{
/* first try to allocate two descriptors */
if (error = falloc (&fp1, &sv[0]))
break;
if (error = falloc (&fp2, &sv[1]))
{
free_first:
/* free first descriptor */
u.u_ofile[sv[0]] = 0;
fp1->f_count = 0;
break;
}
if (error = socreate(domain, &so1, type, protocol))
{
free_second:
u.u_ofile[sv[1]] = 0;
fp2->f_count = 0;
goto free_first;
}
if (error = socreate(domain, &so2, type, protocol))
{
close_so1:
soclose (so1);
goto free_second;
}
if (error = soconnect2(so1, so2))
{
close_so2:
soclose (so2);
goto close_so1;
}
if (type == SOCK_DGRAM)
{
/*
* Datagram socket connection is asymmetric.
*/
if (error = soconnect2(so2, so1))
goto close_so2;
}
}
while (0);
p->p_stat = ostat;
if (error == EINTR)
setrun (FindTask (0));
errno = error;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return error ? -1 : 0;
}
#endif
int
sendto (int s, caddr_t buf, int len, int flags, caddr_t to, int tolen)
{
struct a {
struct socket *so;
caddr_t buf;
int len;
short flags;
caddr_t to;
short tolen;
short err;
int rc;
} uap;
register struct file *fp = getsock (s);
struct user *p = &u;
int ostat;
if (! fp)
return -1;
ostat = p->p_stat;
p->p_stat = SWAIT;
uap.so = fp->f_so;
uap.buf = buf;
uap.len = len;
uap.flags = flags;
uap.to = to;
uap.tolen = tolen;
uap.err = 0;
IN_sendto(p->u_InetBase, &uap);
if (CURSIG (p))
SetSignal (0, SIGBREAKF_CTRL_C);
p->p_stat = ostat;
/* the library doesn't send this to us of course ;-) */
if (uap.err == EPIPE)
_psignal (FindTask (0), SIGPIPE);
if (uap.err == EINTR)
setrun (FindTask (0));
errno = uap.err;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return uap.err ? -1 : uap.rc;
}
int
send (int s, caddr_t buf, int len, int flags)
{
struct a {
struct socket *so;
caddr_t buf;
int len;
short flags;
short err;
int rc;
} uap;
register struct file *fp = getsock (s);
struct user *p = &u;
int ostat;
if (! fp)
return -1;
ostat = p->p_stat;
p->p_stat = SWAIT;
uap.so = fp->f_so;
uap.buf = buf;
uap.len = len;
uap.flags = flags;
uap.err = 0;
IN_send (p->u_InetBase, &uap);
if (CURSIG (p))
SetSignal (0, SIGBREAKF_CTRL_C);
p->p_stat = ostat;
/* the library doesn't send this to us of course ;-) */
if (uap.err == EPIPE)
_psignal (FindTask (0), SIGPIPE);
if (uap.err == EINTR)
setrun (FindTask (0));
errno = uap.err;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return uap.err ? -1 : uap.rc;
}
int
sendmsg (int s, caddr_t msg, int flags)
{
struct a {
struct socket *so;
caddr_t msg;
short flags;
short err;
int rc;
} uap;
register struct file *fp = getsock (s);
struct user *p = &u;
int ostat;
if (! fp)
return -1;
ostat = p->p_stat;
p->p_stat = SWAIT;
uap.so = fp->f_so;
uap.msg = msg;
uap.flags = flags;
uap.err = 0;
IN_sendmsg (p->u_InetBase, &uap);
if (CURSIG (p))
SetSignal (0, SIGBREAKF_CTRL_C);
p->p_stat = ostat;
/* the library doesn't send this to us of course ;-) */
if (uap.err == EPIPE)
_psignal (FindTask (0), SIGPIPE);
if (uap.err == EINTR)
setrun (FindTask (0));
errno = uap.err;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return uap.err ? -1 : uap.rc;
}
int
recvfrom (int s, caddr_t buf, int len, int flags, caddr_t from, int *fromlen)
{
struct a {
struct socket *so;
caddr_t buf;
int len;
short flags;
caddr_t from;
short fromlen;
short err;
int rc;
} uap;
register struct file *fp = getsock (s);
struct user *p = &u;
int ostat;
if (! fp)
return -1;
ostat = p->p_stat;
p->p_stat = SWAIT;
uap.so = fp->f_so;
uap.buf = buf;
uap.len = len;
uap.flags = flags;
uap.from = from;
uap.fromlen = fromlen ? *fromlen : 0;
uap.err = 0;
IN_recvfrom (p->u_InetBase, &uap);
if (CURSIG (p))
SetSignal (0, SIGBREAKF_CTRL_C);
p->p_stat = ostat;
if (uap.err == EINTR)
setrun (FindTask (0));
if (fromlen)
*fromlen = uap.fromlen;
errno = uap.err;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return uap.err ? -1 : uap.rc;
}
int
recv (int s, caddr_t buf, int len, int flags)
{
struct a {
struct socket *so;
caddr_t buf;
int len;
short flags;
short err;
int rc;
} uap;
register struct file *fp = getsock (s);
struct user *p = &u;
int ostat;
if (! fp)
return -1;
ostat = p->p_stat;
p->p_stat = SWAIT;
uap.so = fp->f_so;
uap.buf = buf;
uap.len = len;
uap.flags = flags;
uap.err = 0;
IN_recv (p->u_InetBase, &uap);
if (CURSIG (p))
SetSignal (0, SIGBREAKF_CTRL_C);
p->p_stat = ostat;
if (uap.err == EINTR)
setrun (FindTask (0));
errno = uap.err;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return uap.err ? -1 : uap.rc;
}
int
recvmsg (int s, caddr_t msg, int flags)
{
struct a {
struct socket *so;
caddr_t msg;
short flags;
short err;
int rc;
} uap;
register struct file *fp = getsock (s);
struct user *p = &u;
int ostat;
if (! fp)
return -1;
ostat = p->p_stat;
p->p_stat = SWAIT;
uap.so = fp->f_so;
uap.msg = msg;
uap.flags = flags;
uap.err = 0;
IN_recvmsg (p->u_InetBase, &uap);
if (CURSIG (p))
SetSignal (0, SIGBREAKF_CTRL_C);
p->p_stat = ostat;
if (uap.err == EINTR)
setrun (FindTask (0));
errno = uap.err;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return uap.err ? -1 : uap.rc;
}
int
shutdown (int s, int how)
{
struct a {
struct socket *so;
short how;
short err;
} uap;
register struct file *fp = getsock (s);
struct user *p = &u;
int ostat;
if (! fp)
return -1;
ostat = p->p_stat;
p->p_stat = SWAIT;
uap.so = fp->f_so;
uap.how = how;
uap.err = 0;
IN_shutdown (p->u_InetBase, &uap);
if (CURSIG (p))
SetSignal (0, SIGBREAKF_CTRL_C);
p->p_stat = ostat;
if (uap.err == EINTR)
setrun (FindTask (0));
errno = uap.err;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return uap.err ? -1 : 0;
}
int
setsockopt (int s, int level, int name, caddr_t val, int valsize)
{
struct a {
struct socket *so;
short level;
short name;
caddr_t val;
short valsize;
short err;
} uap;
register struct file *fp = getsock (s);
struct user *p = &u;
int ostat;
if (! fp)
return -1;
ostat = p->p_stat;
p->p_stat = SWAIT;
uap.so = fp->f_so;
uap.level = level;
uap.name = name;
uap.val = val;
uap.valsize = valsize;
uap.err = 0;
IN_setsockopt (p->u_InetBase, &uap);
if (CURSIG (p))
SetSignal (0, SIGBREAKF_CTRL_C);
p->p_stat = ostat;
if (uap.err == EINTR)
setrun (FindTask (0));
errno = uap.err;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return uap.err ? -1 : 0;
}
int
getsockopt (int s, int level, int name, caddr_t val, int *valsize)
{
struct a {
struct socket *so;
short level;
short name;
caddr_t val;
short valsize;
short err;
} uap;
register struct file *fp = getsock (s);
struct user *p = &u;
int ostat;
if (! fp)
return -1;
ostat = p->p_stat;
p->p_stat = SWAIT;
uap.so = fp->f_so;
uap.level = level;
uap.name = name;
uap.val = val;
uap.valsize = valsize ? *valsize : 0;
uap.err = 0;
IN_getsockopt (p->u_InetBase, &uap);
if (CURSIG (p))
SetSignal (0, SIGBREAKF_CTRL_C);
p->p_stat = ostat;
if (uap.err == EINTR)
setrun (FindTask (0));
if (valsize)
*valsize = uap.valsize;
errno = uap.err;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return uap.err ? -1 : 0;
}
#if 0
/* same problem as with socketpair() */
pipe()
{
register struct file *rf, *wf;
struct socket *rso, *wso;
int r;
u.u_error = socreate(AF_UNIX, &rso, SOCK_STREAM, 0);
if (u.u_error)
return;
u.u_error = socreate(AF_UNIX, &wso, SOCK_STREAM, 0);
if (u.u_error)
goto free;
rf = falloc();
if (rf == NULL)
goto free2;
r = u.u_r.r_val1;
rf->f_flag = FREAD;
rf->f_type = DTYPE_SOCKET;
rf->f_ops = &socketops;
rf->f_data = (caddr_t)rso;
wf = falloc();
if (wf == NULL)
goto free3;
wf->f_flag = FWRITE;
wf->f_type = DTYPE_SOCKET;
wf->f_ops = &socketops;
wf->f_data = (caddr_t)wso;
u.u_r.r_val2 = u.u_r.r_val1;
u.u_r.r_val1 = r;
if (u.u_error = unp_connect2(wso, rso))
goto free4;
wso->so_state |= SS_CANTRCVMORE;
rso->so_state |= SS_CANTSENDMORE;
return;
free4:
wf->f_count = 0;
u.u_ofile[u.u_r.r_val2] = 0;
free3:
rf->f_count = 0;
u.u_ofile[r] = 0;
free2:
(void)soo_close(wso);
free:
(void)soo_close(rso);
}
#endif
/*
* Get socket name.
*/
int
getsockname (int fdes, caddr_t asa, int *alen)
{
struct a {
struct socket *so;
caddr_t asa;
short alen;
short err;
} uap;
register struct file *fp = getsock (fdes);
struct user *p = &u;
int ostat;
if (! fp)
return -1;
ostat = p->p_stat;
p->p_stat = SWAIT;
uap.so = fp->f_so;
uap.asa = asa;
uap.alen = alen ? *alen : 0;
uap.err = 0;
IN_getsockname (p->u_InetBase, &uap);
if (CURSIG (p))
SetSignal (0, SIGBREAKF_CTRL_C);
p->p_stat = ostat;
if (uap.err == EINTR)
setrun (FindTask (0));
if (alen)
*alen = uap.alen;
errno = uap.err;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return uap.err ? -1 : 0;
}
/*
* Get name of peer for connected socket.
*/
int
getpeername (int fdes, caddr_t asa, int *alen)
{
struct a {
struct socket *so;
caddr_t asa;
short alen;
short err;
} uap;
register struct file *fp = getsock (fdes);
struct user *p = &u;
int ostat;
if (! fp)
return -1;
ostat = p->p_stat;
p->p_stat = SWAIT;
uap.so = fp->f_so;
uap.asa = asa;
uap.alen = alen ? *alen : 0;
uap.err = 0;
IN_getpeername (p->u_InetBase, &uap);
if (CURSIG (p))
SetSignal (0, SIGBREAKF_CTRL_C);
p->p_stat = ostat;
if (uap.err == EINTR)
setrun (FindTask (0));
if (alen)
*alen = uap.alen;
errno = uap.err;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return uap.err ? -1 : 0;
}
static struct file *
getsock (int fdes)
{
register struct file *fp;
register struct user *p = &u;
if ((unsigned) fdes >= NOFILE)
{
errno = EBADF;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return 0;
}
fp = p->u_ofile[fdes];
if (fp == NULL)
{
errno = EBADF;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return (0);
}
if (fp->f_type != DTYPE_SOCKET && fp->f_type != DTYPE_USOCKET)
{
errno = ENOTSOCK;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return (0);
}
if (fp->f_type == DTYPE_SOCKET && ! p->u_InetBase)
{
errno = EPIPE; /* ????? */
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return 0;
}
return (fp);
}
static int
soo_read (struct file *fp, char *buf, int len)
{
struct a {
struct socket *so;
caddr_t buf;
int len;
short flags;
short err;
int rc;
} uap;
int ostat;
struct user *p = &u;
ostat = p->p_stat;
p->p_stat = SWAIT;
uap.so = fp->f_so;
uap.buf = buf;
uap.len = len;
uap.flags = 0;
uap.err = 0;
IN_recv (p->u_InetBase, &uap);
if (CURSIG (p))
SetSignal (0, SIGBREAKF_CTRL_C);
p->p_stat = ostat;
if (uap.err == EINTR)
setrun (FindTask (0));
errno = uap.err;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return uap.err ? -1 : uap.rc;
}
static int
soo_write (struct file *fp, char *buf, int len)
{
struct a {
struct socket *so;
caddr_t buf;
int len;
short flags;
short err;
int rc;
} uap;
struct user *p = &u;
int ostat;
ostat = p->p_stat;
p->p_stat = SWAIT;
uap.so = fp->f_so;
uap.buf = buf;
uap.len = len;
uap.flags = 0;
uap.err = 0;
IN_send (p->u_InetBase, &uap);
if (CURSIG (p))
SetSignal (0, SIGBREAKF_CTRL_C);
p->p_stat = ostat;
if (uap.err == EINTR)
setrun (FindTask (0));
errno = uap.err;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return uap.err ? -1 : uap.rc;
}
static int
soo_ioctl (struct file *fp, int cmd, int inout, int arglen, caddr_t data)
{
struct a {
struct socket *so;
short cmd;
caddr_t data;
short err;
} uap;
struct user *p = &u;
int ostat;
/* _SIGH_... they left almost everything neatly as it was in the BSD kernel
code they used, but for whatever reason they decided they needed their
own kind of ioctl encoding :-((
Well then, here we go, and map `normal' cmds into CBM cmds: */
switch (cmd)
{
case SIOCADDRT : cmd = ('r'<<8)|1; break;
case SIOCDELRT : cmd = ('r'<<8)|2; break;
case SIOCSIFADDR : cmd = ('i'<<8)|3; break;
case SIOCGIFADDR : cmd = ('i'<<8)|4; break;
case SIOCSIFDSTADDR : cmd = ('i'<<8)|5; break;
case SIOCGIFDSTADDR : cmd = ('i'<<8)|6; break;
case SIOCSIFFLAGS : cmd = ('i'<<8)|7; break;
case SIOCGIFFLAGS : cmd = ('i'<<8)|8; break;
case SIOCGIFCONF : cmd = ('i'<<8)|9; break;
case SIOCSIFMTU : cmd = ('i'<<8)|10; break;
case SIOCGIFMTU : cmd = ('i'<<8)|11; break;
case SIOCGIFBRDADDR : cmd = ('i'<<8)|12; break;
case SIOCSIFBRDADDR : cmd = ('i'<<8)|13; break;
case SIOCGIFNETMASK : cmd = ('i'<<8)|14; break;
case SIOCSIFNETMASK : cmd = ('i'<<8)|15; break;
case SIOCGIFMETRIC : cmd = ('i'<<8)|16; break;
case SIOCSIFMETRIC : cmd = ('i'<<8)|17; break;
case SIOCSARP : cmd = ('i'<<8)|18; break;
case SIOCGARP : cmd = ('i'<<8)|19; break;
case SIOCDARP : cmd = ('i'<<8)|20; break;
case SIOCATMARK : cmd = ('i'<<8)|21; break;
case FIONBIO : cmd = ('m'<<8)|22; break;
case FIONREAD : cmd = ('m'<<8)|23; break;
case FIOASYNC : cmd = ('m'<<8)|24; break;
case SIOCSPGRP : cmd = ('m'<<8)|25; break;
case SIOCGPGRP : cmd = ('m'<<8)|26; break;
default:
/* we really don't have to bother the library with cmds we can't even
map over... */
errno = EINVAL;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return -1;
}
ostat = p->p_stat;
p->p_stat = SWAIT;
uap.so = fp->f_so;
uap.cmd = cmd;
uap.data = data;
uap.err = 0;
IN_ioctl (p->u_InetBase, &uap);
if (CURSIG (p))
SetSignal (0, SIGBREAKF_CTRL_C);
p->p_stat = ostat;
if (uap.err == EINTR)
setrun (FindTask (0));
errno = uap.err;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return uap.err ? -1 : 0;
}
static int
soo_select (struct file *fp, int select_cmd, int io_mode)
{
struct a {
struct socket **sotable; /* just one socket used */
int *inp;
int *out;
int *exc;
void *process;
short exec_sig;
short numfd;
short err;
short rc;
} uap;
int ostat;
struct user *p = &u;
int in, out, exc;
switch (io_mode)
{
case SELMODE_IN:
in = 1; out = 0; exc = 0;
break;
case SELMODE_OUT:
in = 0; out = 1; exc = 0;
break;
case SELMODE_EXC:
in = 0; out = 0; exc = 1;
break;
}
ostat = p->p_stat;
p->p_stat = SWAIT;
uap.sotable = & fp->f_so;
uap.inp = ∈
uap.out = &out;
uap.exc = &exc;
#if 0
uap.process = FindTask (0);
uap.exec_sig = p->u_sigio;
#else
/* sigh, above doesn't work.. */
uap.process = 0;
uap.exec_sig = 0;
#endif
uap.numfd = 1;
uap.err = 0;
IN_select (p->u_InetBase, &uap);
if (CURSIG (p))
SetSignal (0, SIGBREAKF_CTRL_C);
p->p_stat = ostat;
errno = uap.err;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
if (select_cmd == SELCMD_PREPARE)
#if 0
return 1 << p->u_sigio;
#else
return 0;
#endif
else
return uap.rc == 1 ? 1 : 0;
}
static int
soo_close (struct file *fp)
{
struct a {
struct socket *so;
short err;
} uap;
struct user *p = &u;
int err = 0;
ix_lock_base ();
fp->f_count--;
if (fp->f_count == 0)
{
/* don't have the base locked for IN_close, this MAY block!! */
uap.so = fp->f_so;
ix_unlock_base ();
IN_close (p->u_InetBase, &uap);
err = uap.err;
}
else
ix_unlock_base ();
errno = err;
KPRINTF (("&errno = %lx, errno = %ld\n", &errno, errno));
return err ? -1 : 0;
}